package com.ltmonitor.jt808.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ltmonitor.dao.IBaseIbatisDao;
import com.ltmonitor.dao.IDepartmentDao;
import com.ltmonitor.dao.IGPSRealDataDao;
import com.ltmonitor.dao.IGpsMileageDao;
import com.ltmonitor.dao.IOnlineRecordDao;
import com.ltmonitor.dao.IOnlineStaticDao;
import com.ltmonitor.dao.IVehicleDataDao;
import com.ltmonitor.dao.IVehicleOnlineRateDao;
import com.ltmonitor.entity.AlarmRecord;
import com.ltmonitor.entity.Department;
import com.ltmonitor.entity.FuelConsumption;
import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.entity.GpsMileage;
import com.ltmonitor.entity.OnlineRecord;
import com.ltmonitor.entity.OnlineStatistic;
import com.ltmonitor.entity.VehicleData;
import com.ltmonitor.entity.VehicleOnlineRate;
import com.ltmonitor.jt808.service.IStatisticService;
import com.ltmonitor.service.IRealDataService;
import com.ltmonitor.util.Constants;
import com.ltmonitor.util.DateUtil;

/**
 * 定时统计服务，在quartz.xml文件中定时配置
 * 
 * @author DELL
 * 
 */
@Service("statisticService")
public class StatisticService implements IStatisticService {

	@Autowired
	IBaseIbatisDao baseIbatisDao;
	@Autowired
	IGpsMileageDao gpsMileageDao;
	@Autowired
	IOnlineStaticDao onlineStaticDao;
	@Autowired
	IVehicleDataDao vehicleDataDao;
	@Autowired
	IDepartmentDao departmentDao;
	@Autowired
	IVehicleOnlineRateDao vehicleOnlineRateDao;
	@Autowired
	IOnlineRecordDao onlineRecordDao;

	@Autowired
	IGPSRealDataDao GPSRealDataDao;

	@Autowired
	IRealDataService realDataService;

	private static Logger logger = Logger.getLogger(StatisticService.class);

	private double privateMaxOil;

	public final double getMaxOil() {
		return privateMaxOil;
	}

	public final void setMaxOil(double value) {
		privateMaxOil = value;
	}

	/**
	 * 每天创建一个Gps记录表, 同时创建报警表
	 */
	public final void CreateTableForGpsInfo() {
		try {
			for (int m = 1; m < 4; m++) {
				Date nextDay = DateUtil.getDate(new Date(), Calendar.DAY_OF_YEAR, m);
				String tableName = "gpsInfo" + DateUtil.toStringByFormat(nextDay, "yyyyMMdd");
				baseIbatisDao.createGpsInfoTableIfNotExist(tableName);
				// 按天创建报警表
				if (Constants.ALARM_TABLE_FORMAT.equals(Constants.ALARM_TABLE_BY_DAY)) {

					String alarmTableName = Constants.getAlarmTableName(nextDay);
					baseIbatisDao.createNewAlarmTableIfNotExist(alarmTableName);
				}

			}
			// 按月创建报警表
			if (Constants.ALARM_TABLE_FORMAT.equals(Constants.ALARM_TABLE_BY_MONTH)) {

				Date nextMonth = DateUtil.getDate(new Date(), Calendar.MONTH, 1);
				String alarmTableName = Constants.getAlarmTableName(nextMonth);
				baseIbatisDao.createNewAlarmTableIfNotExist(alarmTableName);
			}

		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
	}

	

	// 里程每小时统计一次
	@Transactional
	public final void StaticMileageByHour() {
		java.util.List result = null;
		try {
			Map parameters = new HashMap();
			result = baseIbatisDao.query("selectVehicleMileage", parameters);
		} catch (Exception ex) {
			logger.error(ex.getMessage());

			return;
		}

		Collection<GpsMileage> gmList = this.gpsMileageDao.loadAll();
		Map<String, GpsMileage> gpsMileageMap = new HashMap<String, GpsMileage>();
		for (Object obj : gmList) {
			GpsMileage gm = (GpsMileage) obj;
			gpsMileageMap.put(gm.getPlateNo(), gm);
		}

		logger.warn("**********************static by hour");
		java.util.ArrayList al = new java.util.ArrayList();
		for (Object obj : result) {
			java.util.HashMap ht = (java.util.HashMap) obj;
			String plateNo = (String) ht.get("plateNo");
			double mileage = 0;
			double gas = 0;
			if (ht.get("mileage") != null)
				mileage = Double.parseDouble("" + ht.get("mileage"));
			if (ht.get("gas") != null)
				gas = Double.parseDouble("" + ht.get("gas"));
			try {
				GpsMileage gm = gpsMileageMap.get(plateNo);
				if (gm == null) {
					if (gm == null) {
						gm = new GpsMileage();
						gm.setPlateNo(plateNo);
					}
				}
				FuelConsumption fc = new FuelConsumption();
				fc.setPlateNo(plateNo);
				fc.setMileage1(gm.getMileageLastHour());
				fc.setMileage2(mileage);
				fc.setGas1(gm.getGasLastHour());
				fc.setGas2(gas);
				fc.setMileage(fc.getMileage2() - fc.getMileage1());
				fc.setGas(fc.getGas2() - fc.getGas1());
				fc.setStaticDate(new java.util.Date());
				Calendar cal = Calendar.getInstance();
				cal.setTime(new Date());
				fc.setHour(cal.get(Calendar.HOUR_OF_DAY));
				fc.setIntervalType(FuelConsumption.STATIC_BY_HOUR); // 按小时统计
				al.add(fc);
				gm.setMileageLastHour(mileage);
				gm.setGasLastHour(gas);
				al.add(gm);
				if (al.size() > 10) {
					gpsMileageDao.saveOrUpdateAll(al);
					al.clear();
				}
			} catch (Exception ex) {
				logger.error(ex.getMessage(), ex);
			}

		}

		if (al.size() > 0) {
			gpsMileageDao.saveOrUpdateAll(al);
		}

	}

	/**
	 * 每日结束时，将当前累计里程设置到昨日累计里程，用于准备计算当日里程 = 当前累计里程-昨日累计里程
	 */
	private void upldateLastdayMileage() {
		logger.info("将当前累计里程设置到昨日累计里程");
		try {
			String hql = "update GPSRealData set lastDayMileage = mileage where lastDayMileage <> mileage";

			GPSRealDataDao.bulkUpdate(hql, null);

			List<GPSRealData> ls = realDataService.getOnlineRealDataList();
			for(GPSRealData rd : ls)
			{
				rd.setLastDayMileage(rd.getMileage());
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		
	}

	// 每天统计一次
	@Transactional
	public final void StaticMileageByDay() {
		upldateLastdayMileage();
		logger.info("每日里程统计开始");
		java.util.List result = null;
		try {
			Map parameters = new HashMap();
			result = baseIbatisDao.query("jt808server.selectVehicleMileage", parameters);
			Collection<GpsMileage> gmList = this.gpsMileageDao.loadAll();
			Map<String, GpsMileage> gpsMileageMap = new HashMap<String, GpsMileage>();
			for (Object obj : gmList) {
				GpsMileage gm = (GpsMileage) obj;
				gpsMileageMap.put(gm.getPlateNo(), gm);
			}

			java.util.ArrayList al = new java.util.ArrayList();
			for (Object obj : result) {
				java.util.HashMap ht = (java.util.HashMap) obj;
				String plateNo = (String) ht.get("plateNo");
				double mileage = 0;
				double gas = 0;

				if (ht.get("mileage") != null)
					mileage = Double.parseDouble("" + ht.get("mileage"));
				if (ht.get("gas") != null)
					gas = Double.parseDouble("" + ht.get("gas"));
				try {
					GpsMileage gm = gpsMileageMap.get(plateNo);
					if (gm == null) {
						if (gm == null) {
							gm = new GpsMileage();
							gm.setPlateNo(plateNo);
						}
					}
					FuelConsumption fc = new FuelConsumption();

					fc.setMileage1(gm.getMileageLastDay());
					fc.setMileage2(mileage);
					fc.setGas1(gm.getGasLastDay());
					fc.setGas2(gas);
					fc.setPlateNo(plateNo);
					fc.setMileage((fc.getMileage2() - fc.getMileage1()) / 1.0);
					fc.setGas(fc.getGas2() - fc.getGas1());
					Date today = new java.util.Date();
					fc.setStaticDate(DateUtil.getDate(today, Calendar.DAY_OF_YEAR, -1));

					Calendar cal = Calendar.getInstance();
					cal.setTime(new Date());
					fc.setHour(cal.get(Calendar.HOUR_OF_DAY));
					fc.setIntervalType(FuelConsumption.STATIC_BY_DAY); // 按天统计
					al.add(fc);
					gm.setMileageLastDay(mileage);
					gm.setGasLastDay(gas);
					al.add(gm);
					if (al.size() > 10) {
						gpsMileageDao.saveOrUpdateAll(al);
						al.clear();
					}
				} catch (Exception ex) {
					logger.error(ex.getMessage(), ex);
				}

			}

			if (al.size() > 0) {
				gpsMileageDao.saveOrUpdateAll(al);
			}

		} catch (Exception ex) {
			logger.error(ex.getMessage());

			return;
		}

	}

	/**
	 * 统计每个车辆每天的上线时间，下线时间和上线率
	 */
	@Transactional
	public void staticVehicleOnlineRate() {
		try {
			Date staticDate = DateUtil.getDate(new Date()); // 统计前一天的上线率

			Date startDate = staticDate;
			Date endDate = new Date();
			logger.warn("开始统计车辆上线率,统计时间段:" + startDate + "," + endDate);

			// 对于没有上线记录，也就是当天没上线的车辆，也要生成记录
			List<VehicleData> vehicles = vehicleDataDao.query("from VehicleData where deleted = ?", false);
			java.util.HashMap<String, VehicleOnlineRate> onlineMap = new java.util.HashMap<String, VehicleOnlineRate>();
			List<VehicleOnlineRate> ls = new ArrayList<VehicleOnlineRate>();
			for (VehicleData vd : vehicles) {
				String hql = "from VehicleOnlineRate where plateNo = ? and staticDate = ?";
				VehicleOnlineRate r = (VehicleOnlineRate) this.vehicleOnlineRateDao.find(hql,
						new Object[] { vd.getPlateNo(), staticDate });

				if (r == null) {
					r = new VehicleOnlineRate();
					r.setPlateNo(vd.getPlateNo());
				}
				r.setOnlineTime(0);
				r.setTotalTime(24 * 60);
				onlineMap.put(vd.getPlateNo(), r);
				ls.add(r);
			}

			// java.util.HashMap parameters = new java.util.HashMap();

			String hsql = "from OnlineRecord where ((startTime >= ? and startTime <= ?)"
					+ " or  (endTime >= ? and endTime <= ?) "
					+ " or  ( startTime < ? and endTime > ?)) and alarmType = ? ";

			java.util.List<OnlineRecord> result = onlineRecordDao.query(hsql, new Object[] { startDate, endDate,
					startDate, endDate, startDate, endDate, OnlineRecord.TYPE_ONLINE });
			for (OnlineRecord ar : result) {
				double interval = getInterval(ar, startDate, endDate);
				VehicleOnlineRate r = onlineMap.get(ar.getPlateNo());
				if (r == null) {
					r = new VehicleOnlineRate();
					r.setPlateNo(ar.getPlateNo());
				}
				r.setOnlineTime(interval + r.getOnlineTime());
			}

			for (VehicleOnlineRate r : ls) {
				r.setOfflineTime(r.getTotalTime() - r.getOnlineTime());
				double onlineRate = r.getOnlineTime() * 100 / r.getTotalTime();
				r.setOnlineRate(onlineRate);
				r.setStaticDate(startDate);
			}

			this.vehicleOnlineRateDao.saveOrUpdateAll(ls);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
	}

	private double getInterval(OnlineRecord ar, Date start, Date end) {
		if (ar.getStartTime().compareTo(start) >= 0)
			start = ar.getStartTime();
		if (ar.getEndTime().compareTo(end) <= 0)
			end = ar.getEndTime();

		double interval = com.ltmonitor.util.DateUtil.getSeconds(start, end);
		return interval / 60; // 折算成分钟
	}

	// 统计部门的上线率,在quartz.xml文件中定时配置，每小时统计一次

	@Transactional
	public final void StaticOnlineRate() {
		logger.info("统计部门上线率 by hour");
		java.util.ArrayList<OnlineStatistic> result = new java.util.ArrayList<OnlineStatistic>();
		java.util.HashMap parameters = new java.util.HashMap();

		java.util.HashMap onlineMap = new java.util.HashMap();
		String hsql = "from Department where Deleted = ?";
		try {
			java.util.List departments = this.departmentDao.query(hsql, new Object[] { false });

			// Dictionary<int, Department> departmentMap = new Dictionary<int,
			// Department>();
			for (Object obj : departments) {
				Department dep = (Department) obj;
				OnlineStatistic rc = new OnlineStatistic();
				rc.setDepId(dep.getEntityId());
				rc.setDepName(dep.getName());
				rc.setStatisticDate(new java.util.Date());
				rc.setParentDepId(dep.getParentId());
				onlineMap.put(rc.getDepId(), rc);
				// departmentMap[rc.DepId] = dep;
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);

		}

		// 查询基层车管部门的上线率
		try {
			java.util.List il = baseIbatisDao.query("jt808server.selectOnlineRate", parameters);
			for (Object obj : il) {
				java.util.HashMap ht = (java.util.HashMap) obj;
				Long DepId = Long.parseLong(""+ht.get("DepId"));
				if (onlineMap.containsKey(DepId)) {
					OnlineStatistic rc = (OnlineStatistic) onlineMap.get(DepId);
					while (rc != null) {
						rc.setOnlineNum(rc.getOnlineNum() + Integer.parseInt("" + ht.get("OnlineNum")));
						rc.setVehicleNum(rc.getVehicleNum() + Integer.parseInt("" + ht.get("VehicleNum")));
						if (rc.getVehicleNum() > 0) {
							rc.setOnlineRate((100.00 * rc.getOnlineNum()) / rc.getVehicleNum());
						}

						// 对上级部门进行累计运算
						rc = (OnlineStatistic) onlineMap.get(rc.getParentDepId());
					}
				}
			}
			java.util.ArrayList staticList = new java.util.ArrayList();
			staticList.addAll(onlineMap.values());
			this.onlineStaticDao.saveOrUpdateAll(staticList);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);

		}
	}
}
// : QuartzJobObject